﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace Paxnam
{
    /// <summary>
    /// Classe usada para adicionar objetos na tela contendo um Update e um Draw
    /// </summary>
    abstract class GameObject
    {
        public enum Direction { LEFT, RIGHT, UP, DOWN, STOPPED }

        #region Atributos

        private Texture2D texture;
        public Texture2D Texture
        {
            get
            {
                return texture;
            }
            set
            {
                texture = value;
                //colors = new Color[texture.Width * texture.Height];
                // preenchendo o array com a informação da cor de cada pixel da imagem
                //texture.GetData(colors);
            }
        }

        public int SizeTexture()
        {
            return texture.Width * texture.Height;
        }

       
        protected Color[] colors;

        protected Vector2 position;
        public Vector2 Position
        {
            get { return position; }
            set { position = value; }
        }
        private Vector2 velocity;
        public Vector2 Velocity
        {
            get { return velocity; }
            set { velocity = value; }
        }


        public struct animation
        {
            public int frameWidth;
            public int frameHeight;
            public int frameCount;
            public int frameRate;
            public int mapY;
            public int mapX;
            public int currentFrame;
            public int previousFrame;
           
        }

        
        public animation currentAnimation;
        
        /// <summary>
        /// Não é preciso atualizar a posicao
        /// </summary>
        private Rectangle collisionRect;
        public Rectangle CollisionRect
        {
            get
            {
                return new Rectangle((int)position.X, (int)position.Y, texture.Width, texture.Height);
            }
            set
            {
                collisionRect = value;
            }
        }

        protected GameWindow Window;
        protected Random random;
        private Color color;

        public Color myColor
        {
            get
            {
                return color;
            }
            set
            {
                color = value;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        private bool visible;
        public bool Visible
        {
            get
            {
                return visible;
            }

            set
            {
                visible = value;
            }
        }

        public int timer;
        
        #endregion


        #region Métodos

        /// <summary>
        /// Construtora da Classe
        /// </summary>
        public GameObject()
        {
            Visible = true;
            myColor = Color.White;
            timer = -10;
        }
        /// <summary>
        /// Toda a Lógica do jogo é adicionada aqui
        /// </summary>
        public abstract void Update();

      
        
        public void Draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
            //Window.Title = Convert.ToString(gameTime.TotalGameTime.TotalSeconds);
            if (Visible)
            {
                 
                currentAnimation.currentFrame = (int)(gameTime.TotalGameTime.TotalSeconds *
                    currentAnimation.frameRate) % currentAnimation.frameCount;
               

                
                spriteBatch.Draw(
                    texture,
                    new Rectangle(
                        (int)position.X,
                        (int)position.Y,
                        currentAnimation.frameWidth,
                        currentAnimation.frameHeight),
                    new Rectangle(
                        currentAnimation.currentFrame * currentAnimation.frameWidth,
                        currentAnimation.mapY,
                        currentAnimation.frameWidth,
                        currentAnimation.frameHeight),
                    new Color(
                        1.0f * 1,
                        1.0f * 1,
                        1.0f * 1,
                        1),// 1 = variavel alpha
                    0, //0 = rotation
                    Vector2.Zero,// Zero = variavel pivot
                    SpriteEffects.None,//pode flipar a imagem
                    1);//1 = a camada
               
            }
        }

        public void Draw(GameTime gameTime, SpriteBatch spriteBatch, int currentFrame)
        {
            if (Visible)
            {
               
                spriteBatch.Draw(
                    texture,
                    new Rectangle(
                        (int)position.X,
                        (int)position.Y,
                        currentAnimation.frameWidth,
                        currentAnimation.frameHeight),
                    new Rectangle(
                        currentAnimation.currentFrame * currentAnimation.frameWidth,
                        currentAnimation.mapY,
                        currentAnimation.frameWidth,
                        currentAnimation.frameHeight),
                    new Color(
                        1.0f * 1,
                        1.0f * 1,
                        1.0f * 1,
                        1),// 1 = variavel alpha
                    0, //0 = rotation
                    Vector2.Zero,// Zero = variavel pivot
                    SpriteEffects.None,//pode flipar a imagem
                    1);//1 = a camada


            }
        }

       

        public void Draw(GameTime gameTime, SpriteBatch spriteBatch, SpriteEffects spriteEffects, float rotation, Vector2 pivot)
        {
            
            if (Visible)
            {
                currentAnimation.currentFrame = (int)(gameTime.TotalGameTime.TotalSeconds *
                    currentAnimation.frameRate) % currentAnimation.frameCount;

                spriteBatch.Draw(
                    texture,
                    new Rectangle(
                        (int)position.X,
                        (int)position.Y,
                        currentAnimation.frameWidth,
                        currentAnimation.frameHeight),
                    new Rectangle(
                        currentAnimation.currentFrame * currentAnimation.frameWidth,
                        currentAnimation.mapY,
                        currentAnimation.frameWidth,
                        currentAnimation.frameHeight),
                    new Color(
                        1.0f * 1,
                        1.0f * 1,
                        1.0f * 1,
                        1),// 1 = variavel alpha
                    rotation, //0 = rotation
                    pivot,// Zero = variavel pivot
                    spriteEffects,//pode flipar a imagem
                    1);//1 = a camada

                    


            }
        }

        // Determina se há sobreposição dos pixels não-transparentes entre os dois retangulos
        public bool ColisaoPorPixel(Player other)
        {
            // Encontra os limites do retangulo de interseção
            int cima = Math.Max(this.CollisionRect.Top, other.CollisionRect.Top);

            int baixo = Math.Min(this.CollisionRect.Bottom, other.CollisionRect.Bottom);

            int esquerda = Math.Max(this.CollisionRect.Left, other.CollisionRect.Left);

            int direita = Math.Min(this.CollisionRect.Right, other.CollisionRect.Right);

            // Verifica todos os pontos dentro do limite de intereseção 
            //TODO verificar se os retangulos estao um ao lado do outro
            for (int y = cima; y < baixo; y++)
            {
                for (int x = esquerda; x < direita; x++)
                {
                    // Verifica a cor de ambos os pixels neste momento
                    Color color1 = this.colors[(x - this.CollisionRect.Left) +
                    (y - this.CollisionRect.Top) * this.CollisionRect.Width];
                    Color color2 = other.colors[(x - other.CollisionRect.Left) +
                    (y - other.CollisionRect.Top) * other.CollisionRect.Width];

                    // Se ambos os píxels não são completamente diferentes
                    if (color1.A != 0 && color2.A != 0)
                    {
                        // Um cruzamento de pixel foi encontrado
                        return true;
                    }
                }
            }
            // Não foi encontrado cruzamento entre os pixels
            return false;
        }

        public static double Grau2Rad(double graus)
        {
            return graus*Math.PI/180;
        }

        #endregion
    }
}
